/*
** Copyright (C) QPSOFT.COM All rights reserved.
*/

        /*
        int argument = 1;
        iconv_t icv = iconv_open("UTF-8","unicode");
        if(icv != 0){ // http://hi.baidu.com/anspider/blog/item/b441f5fca962cb1e09244dcc.html
            if(iconvctl (icv ,ICONV_SET_DISCARD_ILSEQ,&argument) == 0) {
                int nRet = iconv(icv,(const char**)&pSrcBuf,(size_t*)&length,&pDstBuf,(size_t*)&length);
                if(nRet == -1) {
                    // include all case of errno: E2BIG, EILSEQ, EINVAL
                    //      E2BIG: There is not sufficient room at *outbuf.
                    //      EILSEQ: An invalid multibyte sequence has been encountered in the input.
                    //      EINVAL: An incomplete multibyte sequence has been encountered in the input
                    // move the left data to the head of szSrcBuf in other to link it with the next data block
                     memmove(buffer2,buffer,length);
                }
                std::cout << buffer2 << "\n" << nRet;
            }
        }
        iconv_close(icv);
        */
        //int r1 =convert("GB2312", "UTF-8", buffer2, length, buffer, length);



#include "extend.h"

// 	SetPixelAndColor(NULL,1920,1080,32);
bool SetPixelAndColor(HDC hdc, unsigned int Width, unsigned int Height, int BitsPerPixel)
{

  DEVMODE CurMode;
  int result=1;
  for(int i=0; result ; i++)
    result = EnumDisplaySettings(NULL, i, &CurMode);
  //CurMode.dmPelsWidth   =GetDeviceCaps(hdc, HORZRES);
  //CurMode.dmPelsHeight  =GetDeviceCaps(hdc, VERTRES);
  //CurMode.dmPelsWidth   = Screen-> Width;
  //CurMode.dmPelsHeight  = Screen-> Height;

  if(CurMode.dmPelsWidth!=Width || CurMode.dmPelsHeight!=Height){
  char s[128];
  sprintf(s,"w %ld h %ld \n",CurMode.dmPelsWidth, CurMode.dmPelsHeight);
  printf(s);
    CurMode.dmPelsWidth   = Width;
    CurMode.dmPelsHeight = Height;
    CurMode.dmBitsPerPel = BitsPerPixel;
    CurMode.dmFields = DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
    result = ChangeDisplaySettings(&CurMode, CDS_UPDATEREGISTRY);

	if (result==DISP_CHANGE_SUCCESSFUL)
		printf("change success");
	else {
		sprintf(s, " rst = %ld", result);
		printf(s);
	}

	return (result==DISP_CHANGE_SUCCESSFUL);
  }
  else
    return false;

}


// http://www.cnblogs.com/phinecos/archive/2008/10/10/1308272.html
string base64_encode(const unsigned char* Data,int DataByte)
{
    //编码表
    const char EncodeTable[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    //返回值
    string strEncode;
    unsigned char Tmp[4]={0};
    int LineLength=0;
    for(int i=0;i<(int)(DataByte / 3);i++)
    {
        Tmp[1] = *Data++;
        Tmp[2] = *Data++;
        Tmp[3] = *Data++;
        strEncode+= EncodeTable[Tmp[1] >> 2];
        strEncode+= EncodeTable[((Tmp[1] << 4) | (Tmp[2] >> 4)) & 0x3F];
        strEncode+= EncodeTable[((Tmp[2] << 2) | (Tmp[3] >> 6)) & 0x3F];
        strEncode+= EncodeTable[Tmp[3] & 0x3F];
        if(LineLength+=4,LineLength==76) {strEncode+="\r\n";LineLength=0;}
    };
    //对剩余数据进行编码
    int Mod=DataByte % 3;
    if(Mod==1)
    {
        Tmp[1] = *Data++;
        strEncode+= EncodeTable[(Tmp[1] & 0xFC) >> 2];
        strEncode+= EncodeTable[((Tmp[1] & 0x03) << 4)];
        strEncode+= "==";
    }
    else if(Mod==2)
    {
        Tmp[1] = *Data++;
        Tmp[2] = *Data++;
        strEncode+= EncodeTable[(Tmp[1] & 0xFC) >> 2];
        strEncode+= EncodeTable[((Tmp[1] & 0x03) << 4) | ((Tmp[2] & 0xF0) >> 4)];
        strEncode+= EncodeTable[((Tmp[2] & 0x0F) << 2)];
        strEncode+= "=";
    };

    return strEncode;
};

string base64_decode(const char* Data,int DataByte,int& OutByte)
{
    //解码表
    const char DecodeTable[] =
    {
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        62, // '+'
        0, 0, 0,
        63, // '/'
        52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // '0'-'9'
        0, 0, 0, 0, 0, 0, 0,
        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
        13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // 'A'-'Z'
        0, 0, 0, 0, 0, 0,
        26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
        39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // 'a'-'z'
    };
    //返回值
    string strDecode;
    int nValue;
    int i= 0;
    while (i < DataByte)
    {
        if (*Data != '\r' && *Data!='\n')
        {
            nValue = DecodeTable[*Data++] << 18;
            nValue += DecodeTable[*Data++] << 12;
            strDecode+=(nValue & 0x00FF0000) >> 16;
            OutByte++;
            if (*Data != '=')
            {
                nValue += DecodeTable[*Data++] << 6;
                strDecode+=(nValue & 0x0000FF00) >> 8;
                OutByte++;
                if (*Data != '=')
                {
                    nValue += DecodeTable[*Data++];
                    strDecode+=nValue & 0x000000FF;
                    OutByte++;
                }
            }
            i += 4;
        }
        else// 回车换行,跳过
        {
            Data++;
            i++;
        }
     }
    return strDecode;
};

/**
cha encode convert GBK to UTF8 (ansi version) xmwen@126.com
*/
extern char *
gbk2utf8(const char *strGBK){

    if (!strGBK){
        return "1";
    }

    int len = MultiByteToWideChar(936, 0, strGBK, -1, NULL,0);
    if (len <1) { return "2"; }

    wchar_t *strUnicode = (wchar_t *) NPN_MemAlloc (sizeof(wchar_t) * len);
    if (!strUnicode){ return "3";   }

    len = MultiByteToWideChar(936, 0, strGBK, -1, strUnicode, len);
    if (len<1){ NPN_MemFree(strUnicode); return "4";  }

    len = WideCharToMultiByte(CP_UTF8, 0, strUnicode, -1, NULL, 0, NULL, NULL);
    if (len<1){ NPN_MemFree(strUnicode); return "5";  }

    char * strUTF8 = (char *) NPN_MemAlloc(sizeof(char) * len);
    if (!strUTF8){ NPN_MemFree(strUnicode); return "6"; }

    len = WideCharToMultiByte (CP_UTF8, 0, strUnicode, -1, strUTF8, len, NULL,NULL);
    NPN_MemFree(strUnicode);
    if (len<1){
        NPN_MemFree(strUTF8);
        return "7";
    }
    return strUTF8;
}

extern char *
utf82gbk(const char *strUTF8) {

    if (!strUTF8){  return "";   }

    int len = MultiByteToWideChar(CP_UTF8, 0, strUTF8, -1, NULL, 0);
    if (len <1) { return ""; }

    wchar_t *strUnicode = (wchar_t *) NPN_MemAlloc (sizeof(wchar_t)*len);
    if (!strUnicode){ return "";   }

    len = MultiByteToWideChar(CP_UTF8, 0, strUTF8, -1, strUnicode, len);
    if (len<1){ NPN_MemFree(strUnicode); return "";  }

    len = WideCharToMultiByte(936, 0, strUnicode, -1, NULL, 0, NULL, NULL);
    if (len<1){ NPN_MemFree(strUnicode); return "";  }

    char * strGBK = (char *) NPN_MemAlloc(len);
    if (!strGBK){ NPN_MemFree(strGBK); return ""; }

    len = WideCharToMultiByte (936, 0, strUnicode, -1, strGBK, len, NULL, NULL);

    NPN_MemFree(strUnicode);
    if (len<1){
        NPN_MemFree(strGBK);
        return "";
    }
    return strGBK;

}

extern char*
conver_text_code(const char* buffer, int length, int* len2, const char* from_code, const char* to_code) {
    UChar* ub = new UChar[length];

    UErrorCode err = U_ZERO_ERROR;

    UCharsetDetector* csd = ucsdet_open(&err);

    const UCharsetMatch *ucm;

    ucsdet_setText(csd, buffer, length, &err);
    ucm = ucsdet_detect(csd, &err);
    const char *name = ucsdet_getName(ucm, &err);
    if (err == U_ZERO_ERROR)
        name = from_code;
    // --------------
    UConverter* conv = ucnv_open(name, &err);

    int len = ucnv_toUChars(conv, ub, length+1, buffer, length+1, &err);
    ucnv_close(conv);

    int tlen = length*2;
    char* cb_targ = new char[tlen];
    memset(cb_targ, 0, tlen);
    UConverter* conv2 = ucnv_open(to_code, &err);
    int lenx = ucnv_fromUChars(conv2, cb_targ, tlen, ub, len, &err);
    *len2 = lenx;
    ucnv_close(conv2);
    return cb_targ;
}
/* ---------------------------------------------------------------- */

/**
function execute a gui process
param:args_str command param
      out std:ostringstream
*/
extern void
executeProccess(char* args_str, std::ostringstream& cout) {

        STARTUPINFO si = { sizeof(STARTUPINFO) };;
        si.cb = sizeof(si);
        si.wShowWindow = SW_SHOW;
        si.dwFlags = STARTF_USESHOWWINDOW;

        PROCESS_INFORMATION pi;
        GetStartupInfo(&si);


        BOOL ret = CreateProcess(
                NULL,  //pszApplicationName
                args_str,
                NULL, // process info
                NULL, // thread info
                TRUE, // inheritable
                0, // creation flags
                NULL, // environment
                NULL, // current directory
                &si,
                &pi);

        if (ret) {
            cout << "ok" << "proc id:" << pi.hProcess << "\n" ;
            cout << "th id: " << pi.hThread << "\n";
        }
        else {
            cout << "fails " << args_str;
            //WaitForSingleObject( pi.hProcess, INFINITE   );
            CloseHandle(pi.hProcess );
            CloseHandle(pi.hThread );
        }

}


extern void
file_exists(char* args_str, std::ostringstream& pcout) {
    if ( !boost::filesystem::exists( "myfile.txt" ) )
      pcout << "NO_EXISTS" << std::endl;
    else
      pcout << "EXISTS" << std::endl;
}


/**
get file list in a directory
param: path specific request res directory
      out std:ostringstream
*/
extern void
getDirectsList(char* path, std::ostringstream& cout) {

  char* split_char = "-|";
  char* con_char = "-";

  fs::path full_path( fs::initial_path<fs::path>() );

  full_path = fs::system_complete( fs::path( path ) );

  if ( !fs::exists( full_path ) ) {
    cout << "\n|-NO_FOUND-|: " << full_path.file_string() << std::endl;
    return;
  }
  uintmax_t fisz = 0;
  std::time_t ltm;
  if ( fs::is_directory( full_path ) ) {

    for (fs::directory_iterator itr(full_path); itr!=fs::directory_iterator(); ++itr)
    {
      try
      {
        if ( fs::is_directory( itr->status() ) ) {
          cout << "D";
        }else {
            if (is_regular_file(itr->status()))
                try {
                    fisz = fs::file_size(itr->path());
                } catch( std::exception const& ex ) {
                    //cerr << itr->path().filename() << " " << ex.what() << endl;
                }
                if (fs::is_symlink(itr->status()) )
                cout << "L";
            cout << "N";
        }
        try {
            ltm = last_write_time(itr->path());
        } catch (  std::exception const& ex  ) {

        }
        cout << con_char << fisz << con_char << ltm ;
        cout << split_char << itr->path().filename() << "\n";

      }
      catch ( const std::exception & ex ) {
        cout << itr->path().filename() << " " << ex.what() << std::endl;
      }
    }

  }
  else // must be a file
  {
    cout << "\nFound: " << full_path.file_string() << "\n";
  }

  return;
};


extern void
read_small_file(const char* file_name, const char* conv_from, const char* conv_to, std::ostringstream& cout) {

    std::fstream rfile;
    rfile.open(file_name, std::fstream::in|std::fstream::binary);
    if(!rfile)
    {
        cout <<"OPEN_FILE_FAILED\0";
        return ;
    };
    //get length of file:
    rfile.seekg(0,std::ios::end);
    long length = rfile.tellg();
    rfile.seekg(0,std::ios::beg);

    //allocate memory:
    char* buffer  = new char[length+1];

    //read data as a block:
    memset(buffer,0,length+1);
    rfile.read(buffer,length);
    buffer[length+1] = '\0';
    if (strlen(conv_to) > 0) {
        int tlen;
        char* buffer2 = conver_text_code(buffer, length+1, &tlen, conv_from, conv_to);
        cout << tlen   << " "<< base64_encode((const unsigned char*)buffer2, tlen);
        buffer2[tlen] = '\0';
        //std::cout << "\n conve result len " << tlen << " context " << buffer2;
        delete buffer2;

    } else {
        cout << length << " "<< base64_encode((const unsigned char*)buffer, length+1);
    }
    rfile.close();

    //MessageBox(NULL, "3!\n ","Java Script",MB_OK);
    delete buffer;

    //cout << std::endl;
}


extern void
file_stat(char* args_str, std::ostringstream& cout) {
    // http://msdn.microsoft.com/en-us/library/gg258117(v=vs.85).aspx
    FILETIME timep;
    SYSTEMTIME timel;

    char *ch;
    WIN32_FIND_DATA fd;
    HANDLE h;
    h=FindFirstFile(args_str,&fd);

    do {
        timep=fd.ftCreationTime;
        FileTimeToSystemTime(&timep,&timel);
        int fatt = fd.dwFileAttributes;
        printf(" %d-%d-%d %d:%d:%d File_Attr %s%s%s%s%s    \t%s \n",
               timel.wYear, timel.wMonth, timel.wDay, timel.wHour, timel.wMinute, timel.wSecond
                , fatt|FILE_ATTRIBUTE_SYSTEM    !=0 ? "S" : "-"
                , fatt|FILE_ATTRIBUTE_DIRECTORY !=0 ? "D" : "-"
                , fatt|FILE_ATTRIBUTE_HIDDEN    !=0 ? "H" : "-"
                , fatt|FILE_ATTRIBUTE_NORMAL    !=0 ? "N" : "-"
                , fatt|FILE_ATTRIBUTE_READONLY  !=0 ? "R" : "-"
                , fd.cFileName
                               );
    }while(FindNextFile(h,&fd));
}


extern void
execute_cmd_command(char* args_str, std::ostringstream& cout) {

        SECURITY_ATTRIBUTES sa;
        HANDLE hRead,hWrite;
        sa.nLength = sizeof(SECURITY_ATTRIBUTES);
        sa.lpSecurityDescriptor = NULL;
        sa.bInheritHandle = TRUE;
        if (!CreatePipe(&hRead,&hWrite,&sa,0)) {
            MessageBox(NULL, "Create Pipe fails!\n ","Java Script",MB_OK);
            return;
        }
        STARTUPINFO si;
        PROCESS_INFORMATION pi;
        si.cb = sizeof(STARTUPINFO);
        GetStartupInfo(&si);
        si.hStdError = hWrite;            //把创建进程的标准错误输出重定向到管道输入
        si.hStdOutput = hWrite;           //把创建进程的标准输出重定向到管道输入
        si.wShowWindow = SW_HIDE;
        si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
        //关键步骤，CreateProcess函数参数意义请查阅MSDN

        if (!CreateProcess(NULL, args_str,NULL,NULL,TRUE,NULL,NULL,NULL,&si,&pi))
        {
            MessageBox(NULL, "Create Proccess fails!\n ","Java Script",MB_OK);
            CloseHandle(hWrite);
            CloseHandle(hRead);
            return;
        }
        CloseHandle(hWrite);
        int szbuf = 4096*1024;
        char* buffer = (char *)NPN_MemAlloc(szbuf);
        ZeroMemory( buffer, szbuf );
        DWORD bytesRead;

        cout.str("");
        cout.clear();
        while (ReadFile(hRead, buffer, szbuf, &bytesRead,NULL) )  {
            cout << buffer;
            ZeroMemory( buffer, szbuf );
        }
        CloseHandle(hRead);
        cout << "\0";
        NPN_MemFree(buffer);

}


int main( int argc, char* argv[] ) {

    std::ostringstream st;
    read_small_file("c:/risk.txt\0", "GB18030", "UTF-8", st);
    std:cout << st.str().c_str();
    if (argc > 2 ) {
        if (strcmp(argv[1] ,"lsdir") ==0 )  {
            getDirectsList(argv[2], st );
            printf(st.str().c_str());
        } else if (strcmp(argv[1] ,"base64") ==0 )  {
            //read_small_file(argv[2], st);
            //cout << st.str().c_str();
        } else printf("cmd error");
    } else printf("argc <2");
}



























